package org.water.common.bind.method;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.data.domain.PageImpl;
import org.springframework.web.context.request.ServletWebRequest;
import org.water.base.entity.R;
import org.water.common.conveter.XmlDateConverter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.thoughtworks.xstream.XStream;

public class ResultFormatReturnValue {

	private static Logger logger=LogManager.getLogger(ResultFormatReturnValue.class);
	/**
	 * jsonp回调方法 参数名
	 */
	public static String CALL_BACK="callback";
	/**
	 * 日期格式
	 */
	public static String dateFormat="yyyy-MM-dd HH:mm:ss"; 
	/**
	 * 转换数据时，包名需要设置为空
	 */
	public String[] packageNameToEmptys={};
	/**
	 * xml转换器
	 */
	public static XStream xstream;
	
	private static ResultFormatReturnValue _instance;
	/**
	 * 单例
	 * @return
	 */
	public static ResultFormatReturnValue instance()
	{
		if(_instance==null) _instance=new ResultFormatReturnValue();
		return _instance;
	}
	
	/**
	 * 设置返回结果值
	 * @param requestUrl
	 * @param obj
	 * @param response
	 * @throws IOException
	 */
	public void setResultValue(Object obj,HttpServletRequest request,HttpServletResponse response) throws IOException
	{
		String accept=request.getHeader("Accept");
		String lastfix="",requestUrl="",jsonpFun=request.getParameter(CALL_BACK);
		if(request instanceof ServletWebRequest) requestUrl=((ServletWebRequest) request).getRequest().getServletPath();
		if(requestUrl.contains(".")) lastfix=requestUrl.substring(requestUrl.lastIndexOf(".")+1);
		if("xml".equalsIgnoreCase(lastfix))  //xml结果
		{
			setResponseResult(response,"xml",obj,null);
		}
		else if("json".equalsIgnoreCase(lastfix)) //json结果
		{
			setResponseResult(response,"json",obj,null);
		}
		else if("jsonp".equalsIgnoreCase(lastfix) && !"".equals(jsonpFun)) //jsonp结果
		{
			setResponseResult(response,"jsonp",obj,jsonpFun);
		}
		else if(accept !=null && (accept.contains("application/xml") || accept.contains("text/xml"))) //xml结果
		{
			setResponseResult(response,"xml",obj,null);
		}
		else if(accept !=null && (accept.contains("application/json") || accept.contains("text/json")))//json结果
		{
			setResponseResult(response,"json",obj,null);
		}
		else if(accept !=null && (accept.contains("text/javascript") || accept.contains("application/javascript")) && !"".equals(jsonpFun)) //jsonp结果
		{
			setResponseResult(response,"jsonp",obj,jsonpFun);
		}
		else
		{
			setResponseResult(response,"text",obj,null);
		}
	}
	/**
	 * 设置返回数据格式
	 * @param response
	 * @param type
	 * @throws IOException 
	 */
    protected void setResponseResult(HttpServletResponse response,String type,Object obj,String jsopFun) throws IOException
    {
    	//response.reset();
    	R result=null;
    	PrintWriter out=response.getWriter();
    	if(obj instanceof R )
    	{
    		result=(R) obj;
    	}
    	else
    	{
    	   result=new R();
    	   if(obj!=null) result.setData(obj);
    	   result.setSuccess(true);
    	}
    	if("xml".equalsIgnoreCase(type))
    	{
    		aliasPackage(obj);
			response.setContentType("application/xml;charset=utf-8");
			out.write(generateXml(result));
			out.flush();
			out.close();
    	}
    	else if("json".equalsIgnoreCase(type))
    	{
    		response.setContentType("application/json;charset=utf-8");
			out.write(generateJson(result));
			out.flush();
			out.close();
    	}
    	else if("jsonp".equalsIgnoreCase(type))
    	{
    		response.setContentType("application/javascript;charset=utf-8");
			out.write(jsopFun+"("+generateJson(result)+")");
			out.flush();
			out.close();
    	}
    	else if("text".equalsIgnoreCase(type))
    	{
    		response.setContentType("text/plain;charset=utf-8");
			out.write(generateJson(result));
			out.flush();
			out.close();
    	}
    	
    }
	
	/**
	 * 生成json数据
	 * @param bean
	 * @return
	 */
	public static String generateJson(R bean)
	{
		String str="";
		SerializerFeature[] features={SerializerFeature.DisableCircularReferenceDetect};
		try {
			str=JSON.toJSONStringWithDateFormat(bean, dateFormat,features);
		} catch (Exception e) {
			logger.info(bean.getData().toString()+" json转换失败");
			e.printStackTrace();
		}
		logger.debug("json:"+str);
		return str;
	}
	/**
	 * 生成xml数据
	 * @param bean
	 * @return
	 */
	public static String generateXml(R bean)
	{
		String str="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
		str=str+xstream.toXML(bean);
		logger.debug("xml:"+str);
		return str;		
	}
	/**
	 * 配置xstream
	 */
	protected void configXstream()
	{
		if(xstream!=null) return;
		xstream=new XStream();
		xstream.autodetectAnnotations(true);
		XmlDateConverter dateConverter=new XmlDateConverter(dateFormat);
		xstream.registerConverter(dateConverter);
//		for(String pk:packageNameToEmptys)
//		{
//			xstream.aliasPackage("", pk);
//		}
	}
	/**
	 * 包名别名 row
	 * @param obj
	 */
	@SuppressWarnings("rawtypes")
	protected void aliasPackage(Object obj)
	{
		if(xstream!=null)
		{
			if(obj instanceof PageImpl)
			{
				PageImpl<?> pageImpl=(PageImpl<?>) obj;
				if(!pageImpl.getContent().isEmpty())
				{
					xstream.alias("row", pageImpl.getContent().get(0).getClass());
				}
			}
			else if(obj instanceof List)
			{
				List list=(List) obj;
				if(!list.isEmpty()) xstream.alias("row", list.get(0).getClass());
			}
		}
	}
}
